// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//
#pragma once

#include <unistd.h>
#include <cstdlib>
#include <memory>
#include <string>

#include <pollux/common/base/exceptions.h>

namespace kumo::pollux::exec::test {
    /// Manages the lifetime of a temporary directory.
    class TempDirectoryPath {
    public:
        /// If 'enableFaultInjection' is true, we enable fault injection on the
        /// created file directory.
        static std::shared_ptr<TempDirectoryPath> create(
            bool enableFaultInjection = false);

        virtual ~TempDirectoryPath();

        TempDirectoryPath(const TempDirectoryPath &) = delete;

        TempDirectoryPath &operator=(const TempDirectoryPath &) = delete;

        /// If fault injection is enabled, the returned file path will have the faulty
        /// file system prefix scheme. The pollux fs then opens the directory through
        /// the faulty file system. The file operation will then either fail or be
        /// delegated to the actual file.
        const std::string &getPath() const {
            return path_;
        }

        /// The actual file path if fault injection is enabled.
        const std::string &getDelegatePath() const {
            return tempPath_;
        }

    private:
        static std::string createTempDirectory();

        explicit TempDirectoryPath(bool enableFaultInjection)
            : enableFaultInjection_(enableFaultInjection),
              tempPath_(createTempDirectory()),
              path_(
                  enableFaultInjection_
                      ? fmt::format("faulty:{}", tempPath_)
                      : tempPath_) {
        }

        const bool enableFaultInjection_{false};
        const std::string tempPath_;
        const std::string path_;
    };
} // namespace kumo::pollux::exec::test
